#ifndef Q3_H
#define Q3_H
#include <algorithm>
#include <cstddef>
#include <fstream>
#include <iostream>
#include <iterator>
#include <ostream>
#include <queue>
#include <sstream>
#include <string>
#include <vector>
namespace q3 {
    struct Flight
    {
	    std::string flight_number;
	    size_t duration;
	    size_t connections;
	    size_t connection_times;
	    size_t price;
        
        friend void operator>>( std::string s , Flight &f );
        friend std::ostream & operator<<(std::ostream & os ,const Flight &f);
        friend std::ostream & operator<<(std::ostream & os , Flight &&f);
    };
    inline bool operator<(const Flight & a, const Flight & b) {
        size_t wa = a.duration + a.connection_times + 3 * a.price;
        size_t wb = b.duration + b.connection_times + 3 * b.price;
        return wa > wb;
    }
    inline bool operator>(const Flight & a, const Flight & b) {
        size_t wa = a.duration + a.connection_times + 3 * a.price;
        size_t wb = b.duration + b.connection_times + 3 * b.price;
        return wa > wb;
    }

    inline void operator<<( Flight & f , std::string s ) {
        std::replace_if( s.begin() , s.end() , []( char a ) {
            return  a == ':';
        },' ');

        std::istringstream iss(s);
        std::string key  ;
        std::string value;
        iss >> key;

        if( key == std::string("flight_number") ) {
            iss >> f.flight_number;
        }   
        else if( key == std::string("duration")) {
            iss >> value;
            std::replace_if( s.begin() , s.end() , []( char a ) {
                return  a == 'h' || a=='m';
            },' ');
            
            std::istringstream isstime(value);
            size_t h , m;
            m = 0;
            isstime >> h;
            isstime >> m;
            if( isstime.fail() )
                m = 0;
            f.duration = h * 60 + m;
        }
        else if( key == std::string("connections")) {
            iss >> f.connections;
        }
            
        else if( key == std::string("connection_times")) {
            iss >> value;
            std::replace_if( value.begin() , value.end() , []( char a ) {
                return  a == ',';
            },' ');
            
            std::string tstr;
            std::stringstream tlss(value);
            size_t total_time = 0;
            do {
                tlss >> tstr;
                std::replace_if( tstr.begin() , tstr.end() , []( char a ) {
                    return  a == 'h' || a=='m';
                },' ');

                std::stringstream tss(tstr);
                size_t h,m;

                tss >> h;
                tss >> m;
                if( tss.fail() )
                    m = 0;
                total_time += h * 60 + m;
            } while( !tlss.eof() );
            f.connection_times = total_time;
        }
        else if (key == std::string("price")) {
            iss >> f.price;
        }
    }
    inline std::ostream & operator<<( std::ostream & os , const Flight &f) {
        os  <<  f.flight_number     << "|"
            <<  f.duration          << " "
            <<  f.connections       << " "
            <<  f.connection_times  << "m "
            <<  f.price;
        return os;
    };
    inline std::ostream & operator<<( std::ostream & os , Flight &&f) {
        os  <<  f.flight_number     << "|"
            <<  f.duration          << " "
            <<  f.connections       << " "
            <<  f.connection_times  << "m "
            <<  f.price;
        return os;
    };

    inline std::priority_queue<Flight> gather_flights( std::string file ) {
        std::fstream fs(file);

        std::vector<Flight> fv;
        std::string entry;

        do {
            std::getline(fs,entry);
            std::replace_if( entry.begin() , entry.end() , []( char a ) {
                return  a == '-';
            },' ');
            
            std::istringstream iss(entry);
            Flight f;
            std::string kv;

            do {
                iss >> kv;
                f << kv;
            }while( !iss.eof() );

            fv.push_back(f);
        }while( !fs.eof() );
        std::copy( fv.begin() , fv.end() ,
            std::ostream_iterator<Flight>(std::cout , "\n" ) );

        std::priority_queue<Flight>
            fpq(fv.begin(),fv.end());
        return fpq;
    }
}

#endif //Q3_H